package aspectos;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

import uqbar.aspectj.utils.Utils;
import dominio.*;
import adicionales.ValorInvalidoExeception;

public aspect ValidadorAspect {
	
	declare parents : dominio.Persona implements ValidadorSupport;

	private ValidarStringNoVacio tempValidador;

	
	pointcut fieldWrite(ValidadorSupport target, Object newValue):
		call(* dominio.Persona.setNombre(*))
		&& args(newValue) 
		&& target(target);
	
	/** La consulta de si es null el validador, es por un conflicto con el asepcto ContadorLlamadasAspect
	 * 	ya que este mira la mismas llamadas que este aspecto, estan capturando el mismo punto de interes, comenzando
	 *  con el ContadorLlamadasAspect y luego este aspecto, al ejecutar el test "ContadorLlamadasTest" el
	 *   validador nunca se instancia, lo cual da un "null pointer exception".
	 *  */
	
	void around(ValidadorSupport target, Object newValue) throws ValorInvalidoExeception: fieldWrite(target,newValue){
		Object oldValue = Utils.getField(target, "nombre");
		target.fieldChanged("nombre", oldValue , newValue);
		if(tempValidador!= null && !tempValidador.isValido()){
			throw new ValorInvalidoExeception("Nombre Invalido");
		}else{
		proceed(target,newValue);
		}
	}
	
	public void agregarValidador(ValidadorSupport p1, String st, ValidarStringNoVacio validador){
		p1.initialize();
		p1.addPropertyChangeListener(st, validador);
		this.tempValidador = validador;
	}
	
	
	private transient PropertyChangeSupport ValidadorSupport.changeSupport;

	
	public void ValidadorSupport.initialize() {
		this.changeSupport = new PropertyChangeSupport(this);
	}
	
	public void ValidadorSupport.addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
		this.changeSupport.addPropertyChangeListener(propertyName, listener);
	}
	
	public void ValidadorSupport.removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
		this.changeSupport.removePropertyChangeListener(propertyName, listener);
	}
		
	public void ValidadorSupport.fieldChanged(String fieldName, Object oldValue, Object newValue) {
		this.changeSupport.firePropertyChange(fieldName, oldValue, newValue);;
	}
	

}
